#include "FtpServer.h"
#include "Protocol/ProtocolApi.h"
#include "ScreenMirrorStream.h"
#include "DiskController.h"
#include "StreamerCurtainPlay.h"
#include "errorCode.h"
#include "ZipUtil.h"

using namespace Protocol;

FtpServer *FtpServer::sm_FtpServer;
mutex FtpServer::sm_instanceLock;

FtpServer *FtpServer::instance(){
    if(sm_FtpServer == nullptr){
        std::lock_guard<std::mutex> lock(sm_instanceLock);
        sm_FtpServer = new FtpServer();
    }
    return sm_FtpServer;
}

FtpServer::FtpServer(){
    RegistRPC();
}

FtpServer::~FtpServer(){

}

void FtpServer::RegistRPC(){
    RPCMethodMap method_map;
	method_map.emplace("GetSavePath", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return GetSavePath(request, inMap, response, outMap);
	}));
	
	method_map.emplace("TrackFile", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return TrackFile(request, inMap, response, outMap);
	}));

	IProtocolInterface::GetInstance()->RegistProtocol("FtpServer", method_map);
}

bool FtpServer::GetSavePath(const Json::Value &request, const Fdt::BufferMap::Ptr &inMap, Json::Value &response, Fdt::BufferMap::Ptr &outMap){
    //判断参数
    if(!request.isMember("Param") || !request["Param"].isMember("operation")){
        errorf("paramer error\n");
        return false;
    }
    std::string path;
    std::string opt = request["Param"]["operation"].asString();
    //根据业务分发给不同的函数做处理
    if(opt == "DigitalSignage"){
        //判断当前是否在投屏，这里需要注意错误码的透传，只要这一层设置了错误码并且return false就行了
        if(Media::ScreenMirrorStream::instance()->getShareScreenStatus())
        {
            response["code"] = Media::ScreenPlaying;
    		response["msg"] = "The device is displaying screen mirroring information, please try again later.";
            LOG_PrintError("The device is displaying screen mirroring information\n");
            return false;
        }


        Media::StreamerCurtainPlay::instance()->stopStreamerCurtain();
        // if(!DigitalSignageFile(path)){
        if(!DiskController::instance()->getRealTimeRootPath(path)){
            return false;
        }else{
            path = path.substr(path.find("/mnt") + 4);
            response["data"]["Param"]["SavePath"] = path;
            return true;
        }
    }
    return true;
}

bool FtpServer::DigitalSignageFile(std::string &path){
    //这里需要确定本次数字标牌的存储路径
    if(!DiskController::instance()->setRealTimeRootPath()){
		LOG_PrintError("faild get root path\n");
		return false;
	}
    //设置压缩文件的存储位置
    DiskController::instance()->getRealTimeBusinessPath(STREAM_ROOT_DIR, m_streamerPath);
    DiskController::instance()->getRealTimeRootPath(m_rootPath);
    //删除上一次的信息
    DiskController::instance()->clearStreamerFiles(STREAM_ROOT_DIR);
    //创建目录返回
    if (mkdir(m_streamerPath.c_str(), 0777) == -1 && errno != EEXIST) {
        LOG_PrintError("cannot creat dir %s\n", m_streamerPath.c_str());
        return false; // 目录创建失败
    }   
    path = m_streamerPath;
    path = path.substr(path.find("/mnt") + 4);

    return true;
}

bool FtpServer::TrackFile(const Json::Value &request, const Fdt::BufferMap::Ptr &inMap, Json::Value &response, Fdt::BufferMap::Ptr &outMap){
   
    //判断参数
    if(!request.isMember("Param") || !request["Param"].isMember("operation")){
        errorf("paramer error\n");
        return false;
    }
    if(!request["Param"].isMember("FileList") || !request["Param"]["FileList"].isArray()){
        errorf("paramer error\n");
        return false;
    }
    Json::Value fileList = request["Param"]["FileList"];
    //这里重新获取路径与前面确定的路径做对比，不相同就直接返回
    if(!DiskController::instance()->isMountPath(m_rootPath)){
        errorf("rootPath: %s not a mount path\n", m_rootPath.c_str());
        return false;
    }
    
    std::string filename;
    std::string md5;
    std::string filePath;
    std::string  calcuMd5;
    ZipUtil zip;
    unsigned int size;
    //MD5校验
    for(int i = 0; i < fileList.size(); i++){
        filename = fileList[i]["filename"].asString();
        md5 = fileList[i]["md5"].asString();
        filePath = m_streamerPath +  filename;
        if(!zip.getMd5(filePath, size, calcuMd5)){
			LOG_PrintError("getMd5  faild\n");
			return false;
		}
        if(calcuMd5 != md5){
            LOG_PrintError("compare md5 faild  calcuMd5:%s     md5:%s\n", calcuMd5.c_str(), md5.c_str());
            return false;
        }
    }
    //开启横幅场景
    if(m_streamerPath.find(AIR_FLASH_PATH) != std::string::npos){
        Media::StreamerCurtainPlay::instance()->playStreamerCurtain(Media::CLIENT_STREAMER, AIR_FLASH_PATH);
    }else{
        Media::StreamerCurtainPlay::instance()->playStreamerCurtain(Media::CLIENT_STREAMER, AIR_UDISK_PATH);
    }
    return true;
}